// =======================================================================
// 
//       Filename:  citerator.cpp
// 
//    Description:  
// 
//        Version:  1.0
//        Created:  25.03.2010 22:00:36
//       Revision:  none
//       Compiler:  g++
// 
//         Author:  Dominik 'domachine' Burgdörfer (-), dominik.burgdoerfer@googlemail.com
//        Company:  -
// 
// =======================================================================

#include "citerator.hpp"
#include <cstdio>

namespace webplodder {
    CIterator::CIterator()
        : mStream(0), mPosition(-1)
    {
        resetCache();
    }

    CIterator::CIterator(std::istream& stream) 
        : mStream(&stream), mPosition(-1)
    {
        resetCache();
    }

    CIterator& CIterator::moveForward() 
    {
        readNextChar();
        ++mPosition;

        return *this;
    }

    char CIterator::currentChar() 
    {
        readNextChar();
        return mCache[1];
    }

    char CIterator::nextChar()
    {
        readNextChar();
        if(mStream->good()) {
            return mCache[2];
        }
        else
            return EOF;
    }

    char CIterator::lastChar()
    {
        return mCache[0];
    }

    void CIterator::readNextChar()
    {
        if(mCachePos[2] == mPosition) {
            char ch;

            if(mStream->good()) {
                ch = static_cast<char>(mStream->get());
                updateCache(ch);

                if(mCache[1] == -1) {
                    if(mStream->good()) {
                        ch = static_cast<char>(mStream->get());
                        ++mPosition;
                        updateCache(ch);
                    }
                }
            }
        }
    }

    void CIterator::updateCache(char ch)
    {
        ++mCachePos[2];

        mCachePos[1] = mCachePos[2] - 1;
        mCachePos[0] = mCachePos[1] - 1;

        mCache[0] = mCache[1];
        mCache[1] = mCache[2];
        mCache[2] = ch;
    }

    bool CIterator::good() const
    {
        return mStream->good();
    }

    bool CIterator::eof() const
    {
        return mStream->eof();
    }

    long CIterator::position() const
       
    {
        return mPosition > -1 ? mPosition : (mPosition+1);
    }

    void CIterator::rewind()
    {
        mStream->seekg(0, std::istream::beg);
        resetCache();
    }

    void CIterator::setStream(std::istream& stream)
    {
        mStream = &stream;
        resetCache();
    }

    void CIterator::resetCache()
    {
        mPosition = -1;

        int i;
        for(i = 0; i < 3; ++i) {
            mCachePos[i] = -1;
            mCache[i] = -1;
        }
    }
}
